package com.hsl.network.net;

import javax.swing.JOptionPane;

import com.hsl.network.listener.MessageReceivedListener;
import com.hsl.network.model.DataManager;
import com.hsl.network.net.handler.TCPHandler;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.LengthFieldPrepender;
import io.netty.handler.codec.MessageToByteEncoder;

public class NetTCPClient extends AbstractNetTcp {
    private Bootstrap client;
    protected DataManager data;
    protected MessageReceivedListener listener;

    public NetTCPClient(DataManager data, MessageReceivedListener listener) {
        super(data, listener, "TCP Client");
        this.data = data;
        this.listener = listener;

    }

    @Override
    public boolean start(String ip, int port, int headLength) {
        try {
            EventLoopGroup bossGroup = new NioEventLoopGroup();
            client = new Bootstrap();
            client.group(bossGroup);
            client.channel(NioSocketChannel.class);
            client.handler(new ChannelInitializer<SocketChannel>() {
                @Override
                protected void initChannel(SocketChannel ch) throws Exception {
                    if (headLength == 0){
                        ch.pipeline().addLast("encoder", new MessageToByteEncoder<byte[]>() {
                            @Override
                            protected void encode(ChannelHandlerContext ctx, byte[] msg, ByteBuf out) throws Exception {
                                out.writeBytes(msg);
                            }
                        });
                    }else {
                        ch.pipeline().addLast("frameLengthDecoder", new LengthFieldBasedFrameDecoder(
                                65535, 0,
                                headLength, 0, headLength));
                        ch.pipeline().addLast("encoder", new LengthFieldPrepender(headLength));
                    }
                    ch.pipeline().addLast("handler", new TCPHandler(data, listener));
                }
            });
            ChannelFuture f = client.connect(ip, port).sync();
            channel = f.channel();
        } catch (Exception e) {
            JOptionPane.showMessageDialog(null, "连接失败", "连接失败", JOptionPane.OK_OPTION);
            return false;
        }
        return true;
    }

    @Override
    public void sendMsg(String text) {
        if (channel == null) {
            JOptionPane.showMessageDialog(null, "未建立连接", "发送异常", JOptionPane.OK_OPTION);
            return;
        }
        byte[] bytes = msg2Bytes(text);
        if (bytes != null) {
            int limit = bytes.length;
            ByteBuf byteBuf = Unpooled.buffer(limit);
            byteBuf.writeBytes(bytes);

            channel.writeAndFlush(byteBuf);
        }
    }

    @Override
    public boolean isServer() {
        return false;
    }
}
